﻿using Radius.NET.Application.Const;
using Radius.NET.Application.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Radius.NET.Application.Util
{
    /// <summary>
    /// 编码流水
    /// </summary>
    public class DocumentNumberGenerator
    {
        private AppSerialNumber _appSerialNumber;
        private int _currentNumber;
        private readonly object _lockObject;
        public delegate void NumManipulationHandler(AppSerialNumber serialNumber);


        public DocumentNumberGenerator(AppSerialNumber appSerialNumber)
        {
            this._appSerialNumber = appSerialNumber;
            this._currentNumber = (int)appSerialNumber.Mantissa;
            this._lockObject = new object();
        }

        #region 获取最新编码
        /// <summary>
        /// 获取最新编码号
        /// </summary>
        /// <param name="func"></param>
        /// <returns></returns>
        public string GenerateNextNumber(NumManipulationHandler func)
        {
            string documentNumber;

            lock (_lockObject)
            {
                if (_appSerialNumber.Format == null || _appSerialNumber.UpdateTime == null)
                {
                    _appSerialNumber.Mantissa = 0;
                }
                else
                {
                    //按年流水
                    if (_appSerialNumber.Format == FlowTypeConst.yyyy)
                    {
                        _appSerialNumber.Format = FlowTypeConst.yyyy;
                        if (!DateTime.Now.ToString(FlowTypeConst.yyyy).Equals(_appSerialNumber.UpdateTime.Value.ToString(FlowTypeConst.yyyy)))
                            _appSerialNumber.Mantissa = 0;
                    }
                    //按月流水
                    if (_appSerialNumber.Format == FlowTypeConst.yyyyMM)
                    {
                        _appSerialNumber.Format = FlowTypeConst.yyyyMM;
                        if (!DateTime.Now.ToString(FlowTypeConst.yyyyMM).Equals(_appSerialNumber.UpdateTime.Value.ToString(FlowTypeConst.yyyyMM)))
                            _appSerialNumber.Mantissa = 0;
                    }
                    //按日流水
                    if (_appSerialNumber.Format == FlowTypeConst.yyyyMMdd)
                    {
                        _appSerialNumber.Format = FlowTypeConst.yyyyMMdd;
                        if (!DateTime.Now.ToString(_appSerialNumber.Format).Equals(_appSerialNumber.UpdateTime.Value.ToString(_appSerialNumber.Format)))
                            _appSerialNumber.Mantissa = 0;
                    }
                }

                var format = _appSerialNumber.Format switch
                {
                    //按账号流水
                    FlowTypeConst.UserAccount => App.User.FindFirst(ClaimConst.Account)?.Value,
                    //无格式流水
                    FlowTypeConst.NoFormat => string.Empty,
                    _ => DateTime.Now.ToString(_appSerialNumber.Format)
                };

                _currentNumber = (int)_appSerialNumber.Mantissa;
                _appSerialNumber.Mantissa = Interlocked.Increment(ref _currentNumber);
                documentNumber = $"{_appSerialNumber.Prefix}{format}{_appSerialNumber.Mantissa?.ToString($"D{_appSerialNumber.Digit}")}";
                func(_appSerialNumber);
            }
            return documentNumber;
        }
        #endregion
    }
}
